/*
 * oemv3_msg.c
 *
 *  Created on: 2012. 3. 8.
 *      Author: root
 */

#include "../includes.h"


_st_obs myObs[2]; //={{0},{0}};
_st_obs myObs2[2]; //={{0},{0}};
_st_timea timea={0};
_st_timea timea2={0};
_st_align align;	//={{0},{0},{0},{0},{0}};

int oemv3_msg_rcvd( char* buf, int offset, int len, int id, int fd);
void decode_range_a(int argc, char *argv[],int id,int fd,_st_obs_data *p);
void decode_satxyz_a(int argc, char *argv[],int id,int fd,_st_obs_data *p);
void init_obs_data(_st_obs *p,int index);
void decode_time_a(int argc, char *argv[],int id,int fd,_st_timea *timea);
void decode_gpgga_a(int argc, char *argv[],int id,int fd,EB_ *EB,TS_	*TRACK,POS_	*POSITION);
void decode_gpzda_a(int argc, char *argv[],int id,int fd,EB_ *EB);
void decode_gpgsv_a(int argc, char *argv[],int id,int fd,EB_ *EB,TS_ *TRACK);
void decode_gpgsa_a(int argc, char *argv[],int id,int fd,EB_ *EB,TS_ *TRACK);
void decode_ptnta_a(int argc, char *argv[],int id,int fd);
void decode_gphdt_a(int argc, char *argv[],int id,int fd);

int parse_string(char *cmdline, char *delim, char **argv);
int Parse_ArgsDelimitChar(char *cmdline, char **argv,char delimit);	//sewon 12-06-18
unsigned long CalculateBlockCRC32( unsigned long ulCount, unsigned char *ucBuffer );

gtime_t epoch2time(double *ep);
gtime_t gpst2time(int week, double sec);

gtime_t epoch2time(double *ep)
{
    const int doy[]={1,32,60,91,121,152,182,213,244,274,305,335};
    gtime_t time={0};
    int days,sec,year=(int)ep[0],mon=(int)ep[1],day=(int)ep[2];

    if (year<1970||2099<year||mon<1||12<mon) return time;

    /* leap year if year%4==0 in 1901-2099 */
    days=(year-1970)*365+(year-1969)/4+doy[mon-1]+day-2+(year%4==0&&mon>=3?1:0);
    sec=(int)floor(ep[5]);
    time.time=(time_t)days*86400+(int)ep[3]*3600+(int)ep[4]*60+sec;
    time.sec=ep[5]-sec;
    return time;
}

gtime_t gpst2time(int week, double sec)
{
    gtime_t t=epoch2time(gpst0);

    if (sec<-1E9||1E9<sec) sec=0.0;
    t.time+=86400*7*week+(int)sec;    //(24h*60m*60sec) * 7day * week
    t.sec=sec-(int)sec;
    return t;
}

double time2gpst(gtime_t t, int *week)
{
    gtime_t t0=epoch2time(gpst0);
    time_t sec=t.time-t0.time;
    int w=(int)(sec/(86400*7));

    if (week) *week=w;
    return (double)(sec-w*86400*7)+t.sec;
}

_st_buf_decode st_bd[2];  // buf decode
void init_st_bd()
{
	st_bd[0].i = 0;
	st_bd[1].i = 0;
}


void push_byte_oemv(char c, int id, int fd)
{
	// ignore crc now buf
	_st_buf_decode *p= &st_bd[id];

	if(c == '*' && p->i!=0)
	{
		//if(iLsiDebugVariable == 2 && id == 0)printf("\n>>>>>>>>>>push_byte_oemv(..) : %s\n",p->buf);
		p->buf[ p->i ] = 0;
		decode_oemv_message(p->buf, id, fd);
		dbgCV(155)printf("oemv2 : %d, oemv1 : %d\n\n",SYSTEM.EB.print_Flag,SYSTEM.EB2.print_Flag);
		p->i = 0;
	}
	if( c =='#' || c =='$')
	{
		p->i = 0;
	}

	p->buf[ p->i ] = c;
	p->i = (p->i + 1) % M_ST_BD_SIZE1 ;

	//p->buf[ p->iHead ] = c;

}

int decode_oemv_message(char *buf,int id,int fd)
{
	int i1;
	char* tokens[STRNUM];
	char* result;
	char* result2;
	int max_token;
	int advance;
	char strTemp[800];
	int argc;
	char* argv[STRNUM];

	dbgCV(2) printf(">>decode:%s\r\n",buf);
//	argc=parse_string(buf,",;*",tokens);
	argc=Parse_ArgsDelimitChar(buf, tokens,',');	//sewon 12-06-18

	dbgCV(2) printf("\n>>> %d, %s \n",argc, tokens[0]);

	max_token = argc;
/*
	if(strstr("FINE", tokens[4]) != NULL) //printf("STATUS : Fine , %s \n", tokens[4]);
		FINE_Flag = OFF;
	else
		FINE_Flag = ON;
*/


//	printf("argc : %d, id : %d, Header : %s  \n", argc, id, tokens[0] );

	if((max_token == 1) || (max_token >= STRNUM)){return 0;}

	if(strcmp("#RANGEA",tokens[0])==0){
		if( fd == fdEB )			decode_range_a(max_token,tokens, id, fd, &myObs[id].d[myObs[id].iH]);
	}
	else if(strcmp("#SATXYZA",tokens[0])==0){
		if( fd == fdEB ) 			decode_satxyz_a(max_token, tokens, id, fd, &myObs[id].d[myObs[id].iHprev]);
	}
	else if(strcmp("#TIMEA",tokens[0])==0 && id == SDATA){
		if( fd == fdEB )			decode_time_a(max_token, tokens, id, fd, &timea);
	}
	else if(strcmp("#RCUPOS",tokens[0])==0 ){
		decode_rcupos_a(max_token, tokens, id, fd);
	}
	else if(strcmp("$GPGGA",tokens[0])==0 ){
		if( fd == fdEB ) 			decode_gpgga_a(max_token, tokens, id, fd, &SYSTEM.EB, &SYSTEM.TRACK, &SYSTEM.POSITION);
	}
	else if(strcmp("$GPZDA",tokens[0])==0 ){
		if( fd == fdEB ) 			decode_gpzda_a(max_token, tokens, id, fd, &SYSTEM.EB);
	}
	else if(strcmp("$GPGSA",tokens[0])==0 ){
		if( fd == fdEB )			decode_gpgsa_a(max_token, tokens, id, fd, &SYSTEM.EB, &SYSTEM.TRACK);
	}
	else if(strcmp("$GPGSV",tokens[0])==0 ){
		if( fd == fdEB )			decode_gpgsv_a(max_token, tokens, id, fd, &SYSTEM.EB, &SYSTEM.TRACK);
	}
	else if(strcmp("$PTNTA",tokens[0])==0 ){	//Rubidium OSC, sewon
		if( fd == fdRbSRO )	decode_ptnta_a(max_token, tokens, id, fd);
	}
	else if(strcmp("$GPHDT",tokens[0])==0 ){//ALIGN DATA, sewon
		if( fd == fdEB2 )		decode_gphdt_a(max_token, tokens, id, fd);
	}
	else return 0;

	return 1;

}
int oemv3_msg_rcvd( char* buf, int offset, int len, int id, int fd)
{
//	advance = nmea_crc_validate(buf, offset, len);
//	advance = CalculateBockCRC32(len,buf);
//
	int i;
	for(i=0; i<len;i++)  push_byte_oemv(buf[i],id,fd);

	return 1;

}
void decode_raw_ephem_a(int argc, char *argv[], int id)
{
	eph_t eph={0};
	gtime_t time;
	int prn,sat;
	unsigned char cbuf[60];

	return ;
//	eph.sat = my_atoi( argv[10] );
//
//	if (!(sat=satno(SYS_GPS,prn)))
//	{
//		//error message
//	}
//
//	time = gpst2time( my_atoi( argv[11] ), my_atoi( argv[12] ) );
//	Printf("Ephem:%d",(unsigned)time.time);//through: debug
//	display_time(time);
//
//	hex_str2bin(argv[13],cbuf);
//	decode_subfrm1(cbuf,&eph);
//
//	hex_str2bin(argv[14],cbuf);
//	decode_subfrm2(cbuf,&eph);
//
//	hex_str2bin(argv[15],cbuf);
//	decode_subfrm3(cbuf,&eph);
//
//	ephd[7] = eph;
}


//#CNT,562192377.450000*<CR><LF>
void decode_cnt(int argc, char *argv[],int id)
{
	_st_obs *p= &myObs[id];
	if( argc != 2) return;
	p->timeInterval[ myObs[id].iHprev ] = my_atof( argv[1]);
}

int range_flag = 0;
int id_flag = 0;

void SetEbDummy()
{
	EB_	*EB = &SYSTEM.EB;
	TS_	*TRACK = &SYSTEM.TRACK;
	POS_	*POSITION = &SYSTEM.POSITION;
	PHP_	*PHP = &SYSTEM.EB.PHP;

	EB->TIME.YEAR = 0;     //test
	EB->TIME.MONTH = 1 ;   //test
	EB->TIME.DAY = 2 ;     //test
	EB->STATUS = EB_STATUS_RUN;
	EB->TASK = OFF;
	EB->LockedCounter = 0;
	EB->almanac_step = EB_SET_LEAPSECOND;
	EB->TIME.HOUR = 11;
	EB->TIME.MINUTE = 22;
	EB->TIME.SECOND = 33;
//	EB->model_name = "OEMV3-RCU";
	EB->RxCheckCounter = 0;

   	if( SYSTEM.TIME.LEAPSECOND ) increase_second_amount(&EB->TIME,  (signed char)SYSTEM.TIME.LEAPSECOND);
   	else increase_second_amount(&EB->TIME, 16);

	EB->LOCKMODE = EB_LOCKED;
	SYSTEM.TRACK.STATUS=wbD5; //3D fix
	SYSTEM.TRACK.DOPTYPE = 0;

}

void decode_range_a(int argc, char *argv[],int id,int fd,_st_obs_data *p)

{
//	FILE *fp[2];
	int i,ii,j,cnt=0;
	int not_first[32]={0};

	int mod =(argc-11)%10;
	if( mod )	return ;

	if(SYSTEM.OPERATION.OPMODE!=OPMODE_OPERATION)	return;
	if( (CONFIG.iCVType==0) || (fd==fdEB2) ) return;
	if( argc<12 )		return;

	dbgCV(125) printf("\n%s>>>00:%s,%d\n",(id==MDATA)?"Master":"Slave",argv[0],argc);
	dbgCV(4947){
		for(i=0;i<argc;i++)printf("\n%s,\n",argv[i]);
	}
	dbgCV(125)
		if( argc < 100 )	printf("RANGEA Rcv Error!\n");

//	_st_obs_data *p= &myObs[id].d[myObs[id].iH];

	dbgCV(2) printf("\ndecode_range_a:%d,%d,%s\n",id,argc,argv[0]);
	if( myObs[id].bStopGetData && 0) return ;
	p->time = gpst2time( my_atoi(argv[5]), (int)(my_atof(argv[6])) );

	/*
	if( check30s() ){
		if( ((int)p->time.time)%30 != 0 ) return ;
	}
	 */
			init_obs_data( &myObs[id], myObs[id].iH );

			if( (!strstr(argv[4],"FINE")) || (!strstr(argv[4],"FINESTEERING")) ) return ;
	//for(i=11; i<argc-12; i=i+10)//10 -> data 포맷 묶음 단위
	for(i=11; i<argc; i=i+10)//10 -> data 포맷 묶음 단위
	{
		//ii <- sat num
		ii = my_atoi( argv[i] )-1;
		if( ii>= 0 && ii<32 ){
//			if( ii == 32-1 )
//			{
//            	msgPrintf("xx");
//			}
			p->b[ ii ] = 1;
			p->obs[ii].time = p->time;
			p->obs[ii].L[ 	not_first[ii] ] = my_atof( argv[i+2]); // printf("%s  : >>>", argv[i+2]);
			p->obs[ii].P[ 	not_first[ii] ] = my_atof( argv[i+4]); //printf("%s  : >>>", argv[i+4]);
			p->obs[ii].D[ 	not_first[ii] ] = my_atof( argv[i+6]); //printf("%s  : >>>", argv[i+6]);
			p->obs[ii].SNR[ 	not_first[ii] ] = my_atof( argv[i+7]);// printf("%s  <<<<\n", argv[i+7]);
			not_first[ii] = 1;
			cnt++;
			dbgCV(4948){
				printf(">>>>%s - %lf\n",(id==0)?"M":"S",p->obs[ii].L[ 	not_first[ii] ]);
				printf(">>>>%s - %lf\n",(id==0)?"M":"S",p->obs[ii].P[ 	not_first[ii] ]);
				printf(">>>>%s - %lf\n",(id==0)?"M":"S",p->obs[ii].D[ 	not_first[ii] ]);
				printf(">>>>%s - %lf\n",(id==0)?"M":"S",p->obs[ii].SNR[ 	not_first[ii] ]);
			}
		}
		else
		{
			dbgCV(3) printf("sat:%d,%s\n",ii,argv[i]);
		}
    	range_flag = 1;
  		id_flag = id;


	}

//	SetEbDummy();

	dbgCV(2){ printf("\n--cnt--:%d\n",cnt); }
	if( cnt > 0)
	{
		myObs[id].iHprev = myObs[id].iH; // save prev. data index.
//		printf("--%d--", myObs[id].iH);
		myObs[id].iH = (myObs[id].iH+1) % M_ST_OBS_SIZE;
//		printf("-/%d--", myObs[id].iH);
//		printf(">>>>>>>>>>>>>>>>myObs[%d].iH = %d \n", id, myObs[id].iH );
		if( myObs[id].iH > (M_ST_OBS_SIZE-2) )
		{
			//myObs[id].bStopGetData = 1;
		//	msgPrintf("데이터한계를 초과했습니다.(%d)",myObs[id].iH );
		}
		myObs[id].iObsCnt++;
	}


}

/*
#SATXYZA, COM1, 0, 72.5, FINESTEERING, 1656, 132270.000,00800000,6f3c,6302;
0.0 ,8
,15 ,-4126251.8624 ,26128880.3404 ,-702724.1454 ,-31156.613 ,1.503144045 ,4.668361332 ,0.000000000 ,0.000000000
,4,-25859817.2585,5263387.4948,-4565179.6831,74780.448,1.477777503,8.553250284,0.000000000,0.000000000
,5,-9875462.0560,11792016.1292,21641076.9725,-67954.938,-1.670907701,2.725832361,0.000000000,0.000000000
,7,-16195009.2288,-8490158.3355,19362507.2905,8946.114,-1.005143779,7.785308219,0.000000000,0.000000000
,2,-20057451.6407,14371099.6583,9211451.9789,107646.041,-3.737928729,2.825098655,0.000000000,0.000000000
,26,-12247995.5300,21258397.8388,9058386.2365,-53323.656,0.301606616,2.697457374,0.000000000,0.000000000
,10,-21481387.9488,-5255215.9165,14760182.9575,-4534.594,1.999491027,6.076270167,0.000000000,0.000000000
,29,7240652.8785,19478348.2250,16630386.4144,73491.121,-0.815817114,4.523148485,0.000000000,0.000000000
*599c7a91
 */
void decode_satxyz_a(int argc, char *argv[],int id,int fd,_st_obs_data *p)
{
	FILE *fp[2];
	int i,ii,j,cnt=0;
	int not_first[32]={0};
	gtime_t time;

//	int mod =(argc-11)%9;
//	if( mod ) return ;

	if(SYSTEM.OPERATION.OPMODE!=OPMODE_OPERATION)	return;
	if( (CONFIG.iCVType==0) || (fd==fdEB2) ) return;
	if( argc<13 )		return;

	dbgCV(125) printf("\n%s>>>00:%s,%d\n",(id==MDATA)?"Master":"Slave",argv[0],argc);

	dbgCV(125)
		if( argc < 100 )	printf("Satxyz Rcv Error!\n");

//	_st_obs_data *p= &myObs[id].d[myObs[id].iHprev];
	dbgCV(2) printf("\ndecode_satxyz_a:%d,%d,%s\n",id,argc,argv[0]);

	if(range_flag == 0 && id_flag != id)	return;
	range_flag = 0;

	if( (!strstr(argv[4],"FINE")) || (!strstr(argv[4],"FINESTEERING")) ) return ;

	time = gpst2time( my_atoi(argv[5]), (int)(my_atof(argv[6])) );
	dbgCV(125)printf("\n>>%s, %lf, %lf",HowOEMV(),time.sec,p->time.sec);
	dbgCV(126)	printf(">>time.sec : %.12lf, p->time.sec ; %.12lf, time.time : %.12lf\n\n",time.sec,p->time.sec,time.time);
	if( time.sec != p->time.sec || time.time != p->time.time  ){
		return ;
	}

	for(i=12; i<argc; i=i+9)//9 -> data 포맷 묶음 단위
	{

		//ii <- sat num
		ii = my_atoi( argv[i] ) -1;
		if( ii>= 0 && ii<32 ){
			p->b_corr[ii] = 1; // has corr. info
			p->corr[ii].x = my_atof( argv[i+1]);
			p->corr[ii].y = my_atof( argv[i+2]);
			p->corr[ii].z = my_atof( argv[i+3]);

			p->corr[ii].corr_clk 	= my_atof( argv[i+4]);
			p->corr[ii].corr_ion 	= my_atof( argv[i+5]);
			p->corr[ii].corr_trop 	= my_atof( argv[i+6]);
			//printf("%d ::::: %d\n",p->b[ii], p->b_corr[ii]);
		}

	}
	if( fd == fdEB )	myObs[id].iXyzCnt++;

//				p->b[ ii ] = 1;
//				p->obs[ii].time
//				p->obs[ii].L[ ii	 ]
//				p->obs[ii].P[ ii	 ]
//				p->obs[ii].D[ ii	 ]
//				p->obs[ii].SNR[ ii  ]



}

//#RCUPOS,xx,yy,zz*xxx<CR><LF>
void decode_rcupos_a(int argc, char *argv[],int id,int fd)
{
	int i;
	int not_first[32]={0};
	char * str[]={"MASTER","SLAVE"};
	gtime_t time;

	if( fd == fdEB2 ) return;

	dbgCV(125) printf("\n%s>>>00:%s,%d\n",HowOEMV(),argv[0],argc);

	if( argc < 4 ) return ;

	_st_obs *p= &myObs[id]; //.d[myObs[id].iHprev];
	i=1;
	p->pos[0] = my_atof( argv[i+0]);
	p->pos[1] = my_atof( argv[i+1]);
	p->pos[2] = my_atof( argv[i+2]);
	if(argc==5) p->InputCableDelay = my_atof( argv[i+3]);
	else        p->InputCableDelay = 0;

	dbgCV(1) printf("\n#RCUPOS(%s):%f, %f, %f\n",str[id],p->pos[0],p->pos[1],p->pos[2]);
}

void init_obs_data(_st_obs *p,int index)
{
	int i;
	for(i=0; i<32; i++){
		p->d[index].b[i]=0;			 // default:have no range info,
		p->d[index].b_corr[i] = 0; // default:have no correction info,
		p->d[index].obs[i].L[ 0 ] = 0;
		p->d[index].obs[i].L[ 1 ] = 0;

		p->d[index].corr[i].x = 0;
		p->d[index].corr[i].y = 0;
		p->d[index].corr[i].z = 0;
		p->d[index].corr[i].corr_clk = 0;
		p->d[index].corr[i].corr_ion = 0;
		p->d[index].corr[i].corr_trop = 0;
		p->d[index].b_corr[i] = 0;

	}
	p->timeInterval[index] = 0;
}
//	#TIMEA,COM1,0,50.5,FINESTEERING,1337,410010.000,00000000,9924,1984;
//	VALID,1.953377165e-09,7.481712815e-08,-12.99999999492,2005,8,25,17,
//	53,17000,VALID*e2fc088c
//  0,              1,		2,   3            4           5           6                          7                    8            9          10                 11
//#TIMEA,COM1, 0,77.5,FINE,1680,48925.000,00a00000,9924,6988;VALID,-0.000000504,0.000000195,-15.00000000011,2012,3,18,13,35,10000,VALID*e188fb9
//#TIMEA,COM1,0,78.5,FINE,1680,366625.000,00e80000,9924,6988;INVALID,0.000000000,
void decode_time_a(int argc, char *argv[],int id,int fd,_st_timea *timea)
{
	int i;
	int not_first[32]={0};
	EB_	*EB = &SYSTEM.EB;

	if(!id) return;
	if( fd == fdEB2 ) return;
//	if(strcmp("VALID",argv[10])!=0)	return;


	dbgCV(125) printf("\n%s>>>00:%s,%d\n",HowOEMV(),argv[0],argc);

	i = 10;

	timea->clock_status = argv[i];
	timea->offset 				 = my_atof(argv[i +1]);
	dbgCV(2)	printf("\n %s : timea.offset:%s,%s:%.2f\n",HowOEMV(),argv[0],argv[i +1],timea->offset);
	timea->offset_std   = my_atof(argv[i +2]);
	timea->utc_offset 	 = my_atof(argv[i +3]);
	timea->utc_year			 = my_atol(argv[i +4]);
	timea->utc_month    = my_atoi(argv[i +5]);
	timea->utc_day	     = my_atoi(argv[i +6]);
	timea->utc_hour	    = my_atoi(argv[i +7]);
	timea->utc_min		 	  = my_atoi(argv[i +8]);
	timea->utc_ms   		= my_atol(argv[i +9]);
	timea->utc_status  = argv[i +10];
	//timea->gps_status  = (strstr(argv[4],"FINE") != NULL );
	timea->gps_status  = ( strstr(argv[10],"INVALID") == NULL );

	if(strcmp("VALID",timea->clock_status)==0){
//		printf("LockedCounter : [%02d]\n",EB->LockedCounter_1);
		EB->LockedCounter_1++;
		EB->UnlockedCounter_1 = 0;
	}
	else{
//		printf("UnLockedCounter : [%02d]\n",EB->UnlockedCounter_1);
		EB->LockedCounter_1 = 0;
		EB->UnlockedCounter_1++;
		timea->offset = 0;	//#120807# sewon
	}
	if(EB->LockedCounter_1>=20)		EB->LOCKMODE = EB_LOCKED;
	if(EB->UnlockedCounter_1>=20)	EB->LOCKMODE = EB_UNLOCKED;

	EB->TIME.HOUR 	= timea->utc_hour;
	EB->TIME.MINUTE	= timea->utc_min;
	EB->TIME.SECOND	= (timea->utc_ms)/1000;

	// sewon 12-07-02 LeapSecond 15->16 Changed
	SYSTEM.EB.LEAPSECOND 	= -(signed char)(timea->utc_offset);
	SYSTEM.TIME.LEAPSECOND 	= SYSTEM.EB.LEAPSECOND;
	if( SYSTEM.EB.LEAPSECOND ) 	increase_second_amount(&EB->TIME,  (signed char)SYSTEM.EB.LEAPSECOND);
	else 						increase_second_amount(&EB->TIME, 16);
	dbgCV(653)	printf("SYSTEM.EB.LEAPSECOND[%02d]\tSYSTEM.TIME.LEAPSECOND[%02d]\n",SYSTEM.EB.LEAPSECOND,SYSTEM.TIME.LEAPSECOND);

	i = EB->TIME.SECOND - EB->prevTODSec;
	if( i < 0 ) i+=60;

	if( iLsiDebugVariable == 3334 )
		printf("<%2d> "
				", %2d:%2d,%2d"
				,TimeSliceCounter
				,EB->TIME.HOUR, EB->TIME.MINUTE, EB->TIME.SECOND
		);

	EB->prevTODSec = EB->TIME.SECOND;
/*
	printf(" %s : ",timea.clock_status );
	printf(" %f : ",timea.offset );
	printf(" %f : ",timea.offset_std);
	printf(" %f : ",timea.utc_offset);
	printf(" %ld : ",timea.utc_year	);
	printf(" %d : ",timea.utc_month );
	printf(" %d : ",timea.utc_day );
	printf(" %d : ",timea.utc_hour );
	printf(" %d : ",timea.utc_min );
	printf(" %ld : ",timea.utc_ms );
	printf(" %s : \n",timea.utc_status );
*/
}
//int avg_count=0;	//sewon	120531
//double lat_sum=0;
//double lon_sum=0;
//double hei_sum=0;
//     0                1                        2                        3    4                          5    6   7     8         9                 10   11             12   13   14
//	$GPGGA,134658.00,5106.9792,N,11402.3003,W,2,09,1.0,1048.47,M,-16.27,M,08,AAAA*60
void decode_gpgga_a(int argc, char *argv[],int id,int fd,EB_ *EB,TS_	*TRACK,POS_	*POSITION)
{
	char c1,c2,c3,c4;
	int i1,i2,i3;
//	EB_	*EB = &SYSTEM.EB;
//	TS_	*TRACK = &SYSTEM.TRACK;
//	POS_	*POSITION = &SYSTEM.POSITION;
//	PHP_	*PHP = &SYSTEM.EB.PHP;
	char *p;
	int degree, minute, frac;
	long lat,lon;
	int dop;
	long int hei;
	double df;
	char tp[100];
	FILE* ffp;

	if(!id) return;
	if( fd == fdEB2 ) return;

	dbgCV(124) printf("\n%s>>>00:%s,%d\n",HowOEMV(),argv[0],argc);

	i1=argc-1;
	i2=i3=0;

	if(argc < 9) {return;}

	if( !EB->bRcvZDA ){
		//write(fdEB,cmdNMEA01,strlen(cmdNMEA01));
		//printf("try Send ZDA cmd\r\n");
//		sprintf(MESG,  "\n try Send ZDA cmd\n" );
//		TransmitMessage((BYTE*)MESG,PORT_CONTROL);
	}

/*
	if( fd == fdEB && ++EB->model_cnt>2 )
	{
		EB->model_cnt = 10;
		EB->model_name = "OEMV2-TDOA-GPS";
	}
	else if( fd == fdEB2 && ++EB->model_cnt>2 )
	{
		EB->model_cnt = 10;
		EB->model_name = "OEMV1-TDOA-GPS";
	}
*/
	if( ++EB->model_cnt>2 )
	{
		EB->model_cnt = 10;
		if( fd == fdEB )			EB->model_name = "OEMV2-TDOA-GPS";
		else if( fd == fdEB2 )	EB->model_name = "OEMV1-TDOA-GPS";
	}

//		bRcvTypeF1000c = 1;

		dbgCV(128){
			printf("\nEB->model_name : %s\n",EB->model_name);
			printf("LEAPSECOND : %d\n",SYSTEM.TIME.LEAPSECOND);
		}
		EB->RxCheckCounter = 0;

	//,GPGGA,031504.000,3625.8386,N,12723.6508,E,1,11,0.8,75.92,M,0.00,M,,
//	int i;
//	i = ((*argv[1+0] - '0')*10) + (*(argv[1+0]+1) - '0');
//	EB->TIME.HOUR = (BYTE)i;
//	i = ((*(argv[1+0]+2) - '0')*10) + (*(argv[1+0]+3) - '0');
//	EB->TIME.MINUTE = (BYTE)i;
//	i = ((*(argv[1+0]+4) - '0')*10) + (*(argv[1+0]+5) - '0');
//	EB->TIME.SECOND = (BYTE)i;
//
//
//	//sewon 12-07-02 LeapSecond 15->16 Changed
//	SYSTEM.EB.LEAPSECOND 	= -(signed char)(timea.utc_offset);
//	SYSTEM.TIME.LEAPSECOND 	= SYSTEM.EB.LEAPSECOND;
//	if( SYSTEM.EB.LEAPSECOND ) increase_second_amount(&EB->TIME,  (signed char)SYSTEM.EB.LEAPSECOND);
//	else increase_second_amount(&EB->TIME, 16);
//	dbgCV(653)	printf("SYSTEM.EB.LEAPSECOND[%02d]\tSYSTEM.TIME.LEAPSECOND[%02d]\n",SYSTEM.EB.LEAPSECOND,SYSTEM.TIME.LEAPSECOND);
//
//	i = EB->TIME.SECOND - EB->prevTODSec;
//	if( i < 0 ) i+=60;
//
//	if( iLsiDebugVariable == 3334 )
//		printf("<%2d> "
//				", %2d:%2d,%2d"
//				,TimeSliceCounter
//				,EB->TIME.HOUR, EB->TIME.MINUTE, EB->TIME.SECOND
//		);
//
//	EB->prevTODSec = EB->TIME.SECOND;

   	//increase_second(&EB->TIME, SYSTEM.TIME.LEAPSECOND);
   	//increase_second(&EB->TIME, 15);

//	p = tokens[1+1];
//	degree = (*p-'0')*10 + (*(p+1)-'0');
//	minute = (*(p+2)-'0')*10 + (*(p+3)-'0');
//	frac = (*(p+5)-'0')*1000 + (*(p+6)-'0')*100 +
//			(*(p+7)-'0')*10 + (*(p+8)-'0');
	p=argv[1+1];
	df = my_atof(p);
	degree = (int)(df/100);
	minute = (int)(df-degree*100);
	frac   = (int)((df-degree*100-minute)*1000);

	if( EB->LOCKMODE==EB_LOCKED ){
		VME.Data.Lat_Degree			=	degree;
		VME.Data.Lat_Minute			=	minute;
		VME.Data.Lat_Second_int		=	(int)((df-degree*100-minute)*60);
		VME.Data.Lat_Second_frac	=	(int)((((df-degree*100-minute)*60.)-VME.Data.Lat_Second_int)*10000);
	}

	lat = degree*3600000 + minute*60000 + frac*60;


	if(*argv[1+2] == 'S') {
		POSITION->CURRENT.LAT = -lat;
	}
	else if(*argv[1+2] == 'N') {
		POSITION->CURRENT.LAT = lat;
	}
//GGA, 154126.000, 3625.8381, N, 12723.6518 ,E,1,08,1.2,74.89,M,0.00,M
	p=argv[1+3];
	df = my_atof(p);
	degree = (int)(df/100);
	minute = (int)(df-degree*100);
	frac   = (int)((df-degree*100-minute)*1000);

	if( EB->LOCKMODE==EB_LOCKED ){
		VME.Data.Lon_Degree			=	degree;
		VME.Data.Lon_Minute			=	minute;
		VME.Data.Lon_Second_int		=	(int)((df-degree*100-minute)*60.);
		VME.Data.Lon_Second_frac	=	(int)((((df-degree*100-minute)*60.)-VME.Data.Lon_Second_int)*10000);
	}

	lon = degree*3600000 + minute*60000 + frac*60;


	if(*argv[1+4] == 'W') {
		POSITION->CURRENT.LON = -lon;
	}
	else if(*argv[1+4] == 'E') {
		POSITION->CURRENT.LON = lon;
	}
	p=argv[1+8];
	hei = my_atof(p)*100;
	POSITION->CURRENT.HEI = hei;

	TRACK->TRACKED = atoi(argv[1+6]);
	p=argv[1+7];
	dop= my_atof(p)*10;
	TRACK->DOP = (short int)dop;

	if(TRACK->TRACKED)
	{
		EB->zero_tracking = 0;
	}
	else
	{
		if(SYSTEM.EB.ANTENNA == ANTENNA_OK)	EB->zero_tracking++;
		else EB->zero_tracking = 0;

	}


//	printf("\ntime:%2d %2d %2d> %2d %2d %2d\n"
//			,EB->TIME.YEAR,EB->TIME.MONTH, EB->TIME.DAY
//			,EB->TIME.HOUR, EB->TIME.MINUTE, EB->TIME.SECOND);

}

//     0             1                         2     3      4         56
//$GPZDA,143042.00,25,08,2005,,*6E
void decode_gpzda_a(int argc, char *argv[],int id,int fd,EB_ *EB)
{
	char c1,c2,c3,c4;
	int i1,i2,i3;
	int hour,min,sec;
	time_   time;

//	EB_	*EB = &SYSTEM.EB;
//	TS_	*TRACK = &SYSTEM.TRACK;
//	POS_	*POSITION = &SYSTEM.POSITION;
//	PHP_	*PHP = &SYSTEM.EB.PHP;

	int degree, minute, frac;
	long lat,lon;
	int dop;
	long int hei;

	if(!id) return;
	if( fd == fdEB2 ) return;

	dbgCV(124) printf("\n%s>>>00:%s,%d\n",HowOEMV(),argv[0],argc);

	i1=argc-1;
	i2=i3=0;

	if(argc < 1) {return;}

    EB->TIME.YEAR 	= (WORD)(WORD)atoi(argv[1+3]);
    EB->TIME.MONTH 	= (BYTE)atoi(argv[1+2]);
    EB->TIME.DAY 	= (BYTE)atoi(argv[1+1]);

//    time.YEAR = (WORD)atoi(tokens[1+3]);
//	time.MONTH = (BYTE)atoi(tokens[1+2]);
//	time.DAY = (BYTE)atoi(tokens[1+1]);

//	i1 = ((*tokens[1+0] - '0')*10) + (*(tokens[1+0]+1) - '0');
//	time.HOUR = (BYTE)i1;
//	i1 = ((*(tokens[1+0]+2) - '0')*10) + (*(tokens[1+0]+3) - '0');
//	time.MINUTE = (BYTE)i1;
//	i1 = ((*(tokens[1+0]+4) - '0')*10) + (*(tokens[1+0]+5) - '0');
//	time.SECOND = (BYTE)i1;
//	//increase_second(&EB->TIME, SYSTEM.TIME.LEAPSECOND);
//	SYSTEM.TIME.LEAPSECOND = 15 ;
//	increase_second(&time, 15);
//
//   	printf("\n##:%2d,%2d,> "
//   			", %2d ,%2d,>"
//   			", %2d:%2d,%2d"
//   			,TimeSliceCounter, time.SECOND!=SYSTEM.TIME.GPS.SECOND
//   			, time.SECOND ,SYSTEM.TIME.GPS.SECOND
//   			,SYSTEM.TIME.GPS.HOUR, SYSTEM.TIME.GPS.MINUTE, SYSTEM.TIME.GPS.SECOND );


//   	i1 = ((*tokens[1+0] - '0')*10) + (*(tokens[1+0]+1) - '0');
//   	EB->TIME.HOUR = (BYTE)i1;
//   	i1 = ((*(tokens[1+0]+2) - '0')*10) + (*(tokens[1+0]+3) - '0');
//   	EB->TIME.MINUTE = (BYTE)i1;
//   	i1 = ((*(tokens[1+0]+4) - '0')*10) + (*(tokens[1+0]+5) - '0');
//   	EB->TIME.SECOND = (BYTE)i1;
//   	//increase_second(&EB->TIME, SYSTEM.TIME.LEAPSECOND);
//   	increase_second(&EB->TIME, 15);

//	sprintf(MESG,  "\nrcv ZDA \n" );
//	TransmitMessage((BYTE*)MESG,PORT_CONTROL);
//	SYSTEM.TIME.LEAPSECOND = 15;
   	if( !EB->bRcvZDA && SYSTEM.TIME.LEAPSECOND ){
   		EB->bRcvZDA = 1;
		EB->almanac_step = EB_SET_LEAPSECOND;
		EB->STATUS = EB_STATUS_RUN;
		EB->TASK = OFF;
		EB->LockedCounter = 0;

		EB->once_receiver_detect = ON;

		MessageOut("EB-RUN\r\n");
		LogIt(LOG_CATA1_NORM, LOG_CATA2_NOTHING, LOG_EB_In,0);
   	}

}

//     0             1   2    3      4      5     6      7      8      9    10    11    12      1314 1516
//$GPGSA,M,3,17,02,30,04,05,10,09,06,31,12,,,1.2,0.8,0.9*35
void decode_gpgsa_a(int argc, char *argv[],int id,int fd,EB_ *EB,TS_ *TRACK)
{
	char c1,c2,c3,c4;
	int i,i1,i2,i3;

//	EB_	*EB = &SYSTEM.EB;
//	TS_	*TRACK = &SYSTEM.TRACK;
//	POS_	*POSITION = &SYSTEM.POSITION;
//	PHP_	*PHP = &SYSTEM.EB.PHP;

	int degree, minute, frac;
	long lat,lon;
	int dop;
	long int hei;

	if(!id) return;
	if( fd == fdEB2 ) return;

	dbgCV(124) printf("\n%s>>>00:%s,%d\n",HowOEMV(),argv[0],argc);

	i1=argc-1;
	i2=i3=0;

	if(argc < 3) {return;}
	if(*argv[1+1] == '3'){
//		fr_fixinfo = 3;
    	//EB->LOCKMODE = EB_3D_FIX;
//    	EB->LOCKMODE = EB_LOCKED;
    	TRACK->STATUS=wbD5; //3D fix
    	TRACK->DOPTYPE = 0;
	}
	else if(*argv[1+1] == '2'){
//        EB->LOCKMODE = EB_LOCKED;
        TRACK->STATUS=wbD4; //2D fix
        TRACK->DOPTYPE=0;
//		fr_fixinfo = 2;
	}
	else{
		TRACK->STATUS=0; //2D fix
		TRACK->DOPTYPE=0;
      EB->LOCKMODE = EB_UNLOCKED;
//		fr_fixinfo = 1;
	}

	if( frc_error.gps ){
		TRACK->STATUS=0; //2D fix
		TRACK->DOPTYPE=0;
      EB->LOCKMODE = EB_UNLOCKED;
//		fr_fixinfo = 1;
	}

//	for(i=0;i<(argc-2) && i<12; i++ )
	for(i=0;i<(argc-6) && i<12; i++ )	//sewon 12-06-15
	{
		TRACK->PRN_USED[i]=atoi(argv[3+i]);
	}
	for(;i<12; i++ )
	{
		TRACK->PRN_USED[i]=0;
	}

}

//     0             1   2    3      4      5      6        7     8      9      10     11    12   13      14     15   16    17     18     19
//$GPGSV,3,1,11,18,87,050,48,22,56,250,49,21,55,122,49,03,40,284,47*78
//$GPGSV,3,2,11,19,25,314,42,26,24,044,42,24,16,118,43,29,15,039,42*7E
//$GPGSV,3,3,11,09,15,107,44,14,11,196,41,07,03,173,*4D
//$GLGSV,2,1,06,65,64,037,41,66,53,269,43,88,39,200,44,74,25,051,*64
//$GLGSV,2,2,06,72,16,063,35,67,01,253,*66
void decode_gpgsv_a(int argc, char *argv[],int id,int fd,EB_ *EB,TS_ *TRACK)
{
	char c1,c2,c3,c4;
	int i1,i2,i3;

//	EB_	*EB = &SYSTEM.EB;
//	TS_	*TRACK = &SYSTEM.TRACK;
//	POS_	*POSITION = &SYSTEM.POSITION;
//	PHP_	*PHP = &SYSTEM.EB.PHP;

	int degree, minute, frac;
	long lat,lon;
	int dop;
	long int hei;

	if(!id) return;
	if( fd == fdEB2 ) return;

	dbgCV(124) printf("\n%s>>>00:%s,%d\n",HowOEMV(),argv[0],argc);

	i1=argc-1;
	i2=i3=0;

	if( argc < 5 ) {return;}


	c4 = atoi(argv[1+0]);		//total number of sentence
	c1 = atoi(argv[1+1]);		//current number of sentence
	TRACK->VISIBLE  = atoi(argv[1+2]);		//total number of satellites in view
	//c3 = atoi(tokens[1+3]);		//visible number
	//c4 = atoi(tokens[1+4]);		//elevation
	//i3 = atoi(tokens[1+5]);		//AZ

	if	   (c1 == 1) c3 = 0; // index
	else if(c1 == 2) c3 = 4;
	else if(c1 == 3) c3 = 8;
	else if(c1 == 4) c3 = 12;
	else { printf("$GPGSV decoding warning!\n"); return ; }

	for(i2=0;i2<4 && i2<(argc-4)/4;i2++)
	{
		TRACK->VIS_SAT[c3+i2].ID 		= atoi( argv[ 4*(i2+1)   ] );
		TRACK->VIS_SAT[c3+i2].EL 		= atoi( argv[ 4*(i2+1)+1 ] );
		TRACK->VIS_SAT[c3+i2].AZ 		= atoi( argv[ 4*(i2+1)+2 ] );
		TRACK->VIS_SAT[c3+i2].HEALTH 	= atoi( argv[ 4*(i2+1)+3 ] ); // C/N0
		/*if(TRACK->VIS_SAT[c3+i2].HEALTH != 0) sat_tracking++;*/
	}

	for(;i2<4;i2++)
	{
		TRACK->VIS_SAT[c3+i2].ID = 0;
		TRACK->VIS_SAT[c3+i2].EL = 0;
		TRACK->VIS_SAT[c3+i2].AZ = 0;
		TRACK->VIS_SAT[c3+i2].HEALTH = 0;
	}
	if( c1 == c4 ){

		i2 = c3+i2;
		for( ;i2<12;i2++){ // fill with zero to not assigned field.
			TRACK->VIS_SAT[c3+i2].ID = 0;
			TRACK->VIS_SAT[c3+i2].EL = 0;
			TRACK->VIS_SAT[c3+i2].AZ = 0;
			TRACK->VIS_SAT[c3+i2].HEALTH = 0;
		}

		for( i2 = 0; i2 < 12; i2++){
			TRACK->SAT[i2].ID 	= TRACK->VIS_SAT[i2].ID;
			if( checkPRNused(TRACK->VIS_SAT[i2].ID) ) TRACK->SAT[i2].MODE 	= 8;
			else TRACK->SAT[i2].MODE 	= 0;
			TRACK->SAT[i2].SS 	= TRACK->VIS_SAT[i2].HEALTH;
			TRACK->SAT[i2].STATUS = 0;
		}
	}
	EB->once_receiver_detect = ON;
	EB->TASK = OFF;
	EB->RxCheckCounter = 0;

}
//SRO-100 Rubidium NMEA
// 0                 1                                      2   3      4                   5          6
//$PTNTA,yyyymmddhhnnss,q,T3,rrrrrrr,sfff,s,x,y∗cs<CR><LF>
void decode_ptnta_a(int argc, char *argv[],int id,int fd)
{
	int i;
	char buf[50];
	char sign;

	if( (fd==fdEB) || (fd==fdEB2)) return;

	if( (argc<6) || (argc>9) ) return;

	dbgCV(147) printf("\n%s>>>00:%s,%d\n",HowOEMV(),argv[0],argc);

	rb.comm_ready = YES;

	rb.sro100.quality 			= my_atoi(argv[2]);
	rb.sro100.time_interval 	= my_atoi(argv[4]);

	rb.sro100.general_status 	= my_atoi(argv[6]);

//	rb.sro100.Error_counter = 0;
	dbgCV(140)	printf("%d,%d,%d\n",
							rb.sro100.quality,rb.sro100.time_interval,rb.sro100.general_status);
}

//0                 1                    2
//$GPHDT,75.5664,T*36
void decode_gphdt_a(int argc, char *argv[],int id,int fd)
{
	int i;
	char buf[20];
	float heading_tmp=0;

	if( (argc!=3) || (strcmp("T",argv[2]) != 0) ){
		return;
	}

	align.heading.heading 		= my_atof(argv[1]);

	//Heading Value Update//
	heading_tmp = align.heading.heading + 90.0;
	if( heading_tmp>360.0 ) heading_tmp-=360.0;

	VME_BlockRam_Write(VME_ADDR_HEADING,(int)(heading_tmp*100));

	dbgCV(143)	printf("[ALIGN HEADING] %.4lf\n",align.heading.heading);
}

int parse_string(char *cmdline, char *delim, char **argv)
{
	char *tok;
	int argc = 0;
	argv[argc] = NULL;

	//for(tok = strtok(cmdline, delim); tok && argc<16; tok = strtok(NULL, delim))
	for(tok = strtok(cmdline, delim); tok && argc<400; tok = strtok(NULL, delim))
	{
		argv[argc++] = tok;
	}
	return argc;
}



#define CRC32_POLYNOMIAL 0xEDB88320L
/* --------------------------------------------------------------------------
Calculate a CRC value to be used by CRC calculation functions.
-------------------------------------------------------------------------- */
unsigned long CRC32Value(int i)
{
	int j;
	unsigned long ulCRC;
	ulCRC = i;
	for ( j = 8 ; j > 0; j-- )
	{
		if ( ulCRC & 1 )
		ulCRC = ( ulCRC >> 1 ) ^ CRC32_POLYNOMIAL;
		else
		ulCRC >>= 1;
	}
	return ulCRC;
}
/* --------------------------------------------------------------------------
Calculates the CRC-32 of a block of data all at once
-------------------------------------------------------------------------- */
unsigned long CalculateBlockCRC32(
unsigned long ulCount, /* Number of bytes in the data block */
unsigned char *ucBuffer ) /* Data block */
{
	unsigned long ulTemp1;
	unsigned long ulTemp2;
	unsigned long ulCRC = 0;

	while ( ulCount-- != 0 )
	{
		ulTemp1 = ( ulCRC >> 8 ) & 0x00FFFFFFL;
		ulTemp2 = CRC32Value( ((int) ulCRC ^ *ucBuffer++ ) & 0xff );
		ulCRC = ulTemp1 ^ ulTemp2;
	}
	return( ulCRC );
}


int Parse_ArgsDelimitChar(char *cmdline, char **argv,char delimit)
{
	int argc=0;
	char *s=cmdline;

	if( !cmdline || !(*cmdline) ) return 0;

	argv[argc]=cmdline;
	while(*s)
	{
		//$abc\0,12,3,,5,*
		if((*s == delimit)  || (*s == ';') || (*s == '*'))
		{
			*s = NULL;
			argc++;
			argv[argc] = s+1;
		}
		s++;
	}
	return (argc+1);
}
